﻿using App.Model;
using OxyPlot;
using OxyPlot.Annotations;
using OxyPlot.Legends;
using OxyPlot.Series;
using OxyPlot.WindowsForms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows.Forms;

namespace App.UI
{
    internal class LineChart : PlotView
    {
        private PlotModel plotModel;
        private Dictionary<string, int[]> copie = new Dictionary<string, int[]>();

        public LineChart()
        {
            this.Dock = DockStyle.Fill;
            plotModel = CreatePlotModel();
            plotModel.MouseDown += HandleMouseDown;
            this.Model = plotModel;
        }

        private PlotModel CreatePlotModel()
        {
            PlotModel plotModel = new PlotModel()
            { 
                IsLegendVisible = false 
            };
            plotModel.Legends.Add(new Legend
            {
                LegendPosition = LegendPosition.TopCenter,
                LegendOrientation = LegendOrientation.Horizontal,
                LegendPlacement = LegendPlacement.Outside
            });
            return plotModel;
        }

        public void HandleMouseDown(object sender, OxyMouseDownEventArgs e)
        {
            LineSeries series = e.HitTestResult.Element as LineSeries;
            if (series is LineSeries clickedSeries)
            {
                string[] parts = clickedSeries.Title.Split('-');
                string[] names = Mock.GetNames(parts[0]);
                Drager drager = new Drager();
                drager.Default = copie[names[0]];
                drager.Standard = copie[names[1]];
                drager.Names = names;
                DataObject dataObject = new DataObject("LineSeries", drager);
                this.DoDragDrop(dataObject, DragDropEffects.Copy);
            }
        }

        private LineSeries CreateLineSeries(string title, int[] points)
        {
            LineSeries series = new LineSeries
            {
                Title = title,
                MarkerType = MarkerType.Circle,
                MarkerSize = 4,
                MarkerStroke = OxyColors.White,
                MarkerFill = OxyColors.Blue,
                LineStyle = LineStyle.Solid,
                IsVisible = false,
                InterpolationAlgorithm = InterpolationAlgorithms.CanonicalSpline
            };

            AddDataPointsToSeries(series, points);
            return series;
        }

        private void AddDataPointsToSeries(LineSeries series, int[] points)
        {
            for (int i = 0; i < points.Length; i++)
            {
                series.Points.Add(new DataPoint(i, points[i]));
            }
        }

        public void AddLineSeries(string title, int[] points)
        {
            copie.Add(title, points);
            LineSeries series = CreateLineSeries(title, points);
            series.IsVisible = true;
            plotModel.Series.Insert(0, series);
            this.InvalidatePlot(true);
        }

        public void RemoveLineSeries(string title)
        {
            copie.Remove(title);
            LineSeries seriesToRemove = plotModel.Series
                   .OfType<LineSeries>()
                   .FirstOrDefault(s => s.Title == title);

            if (seriesToRemove != null)
            {
                plotModel.Series.Remove(seriesToRemove);
                this.InvalidatePlot(true);
            }
        }

        public void UpdateAnnotations()
        {
            AnnotationHandler annotationHandler = new AnnotationHandler(plotModel);
            annotationHandler.RemoveUnusedAnnotations();
            annotationHandler.AddAnnotationsToVisibleSeries();
        }
    }

    internal class AnnotationHandler
    {
        private PlotModel plotModel;

        public AnnotationHandler(PlotModel plotModel)
        {
            this.plotModel = plotModel;
        }

        public void RemoveUnusedAnnotations()
        {
            List<Annotation> annotationsToRemove = new List<Annotation>();

            foreach (Annotation annotation in plotModel.Annotations)
            {
                if (annotation is TextAnnotation textAnnotation)
                {
                    LineSeries series = plotModel.Series.OfType<LineSeries>()
                        .FirstOrDefault(s => Mock.CheckName(s.Title, textAnnotation.Text));

                    if (series == null || !series.IsVisible)
                    {
                        annotationsToRemove.Add(annotation);
                    }
                }
            }

            foreach (Annotation annotation in annotationsToRemove)
            {
                plotModel.Annotations.Remove(annotation);
            }
        }

        public void AddAnnotationsToVisibleSeries()
        {
            foreach (LineSeries series in plotModel.Series.OfType<LineSeries>())
            {
                if (series.IsVisible && !HasAnnotation(series.Title))
                {
                    AddAnnotation(series);
                }
            }
        }

        private bool HasAnnotation(string title)
        {
            return plotModel.Annotations.OfType<TextAnnotation>().Any(a => a.Text == title);
        }

        private void AddAnnotation(LineSeries series)
        {
            if (series.Points.Count > 0)
            {
                DataPoint lastPoint = series.Points.Last();
                TextAnnotation label = new TextAnnotation
                {
                    Text = series.Title,
                    TextPosition = lastPoint,
                    Stroke = OxyColors.Transparent,
                    TextColor = OxyColors.Black,
                    FontSize = 12,
                    TextVerticalAlignment = OxyPlot.VerticalAlignment.Bottom,
                    TextHorizontalAlignment = OxyPlot.HorizontalAlignment.Right
                };
                plotModel.Annotations.Add(label);
            }
        }
    }
}
